﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Algobox.JuicyLib.SQL.LiquidView;

namespace LiquidTrading.LiquidViewSyncTool
{
    public class ProcessBats
    {
        const int SYMBOL_NUM_COL = 17;
        const int TICK_NUM_COL = 3;

        const char SEPERATOR_ROW = '\n';
        const char SEPERATOR_COL = ',';

        const int SYMBOL_PRI_NAME = 0;
        const int SYMBOL_PRI_UMTF = 1;
        const int SYMBOL_PRI_ISIN = 2;        
        const int SYMBOL_PRI_MIC = 4;

        const int SYMBOL_LOC_CCY = 3;
        const int SYMBOL_LOC_TICK = 8;

        const int SYMBOL_LOC_REF_PRICE = 9;
        const int SYMBOL_LOC_PREV_CLOSE = 10;

        const int SYMBOL_PRI_BBG = 12;
        const int SYMBOL_LOC_BBG = 13;

        const int TICK_NAME = 0;
        const int TICK_MIN = 1;
        const int TICK_SIZE = 2;

        public static bool ProcessTicks(LiquidViewLinqDataContext linq, ref string ticks)
        {
            string[] rows = ticks.Split(SEPERATOR_ROW);
            string[] data;

            Dictionary<decimal, decimal> pair;
            Dictionary<string, Dictionary<decimal, decimal>> ranges = new Dictionary<string, Dictionary<decimal, decimal>>();

            decimal min;
            decimal size;
            string name;
            
            int end = rows.Length - 1;

            for (int start = 2; start < end; start++)
            {
                data = rows[start].Trim().Split(SEPERATOR_COL);

                if (data.Length == TICK_SIZE + 1 && data[TICK_SIZE] != String.Empty)
                {
                    name = data[TICK_NAME];

                    if (!Decimal.TryParse(data[TICK_MIN], out min))
                        linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Bats Ticks - Couldn't decode TICK_MIN " + data[TICK_MIN], null);

                    if (!Decimal.TryParse(data[TICK_SIZE], out size))
                        linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Bats Ticks - Couldn't decode TICK_SIZE " + data[TICK_SIZE], null);

                    if (!ranges.TryGetValue(name, out pair))
                    {
                        pair = new Dictionary<decimal, decimal>();
                        ranges.Add(name, pair);
                    }
                    ranges[name].Add(min, size);
                }
            }

            long? tickSizeId = null;

            // insert non dynamic - or fixed - tick sizes
            foreach (string tickName in ranges.Where(a => a.Value.Count == 1).Select(a => a.Key))
            {
                KeyValuePair<decimal, decimal> range = ranges[tickName].First();

                try
                {

                    int result = linq.ImportTickSize(tickName, "BATE", null, range.Value, ref tickSizeId);

                    if (result != 4)
                    {
                        if (result == 0)
                        {
                            Console.WriteLine("Created " + tickName);
                            linq.ExceptionHandlerThrow("LiquidViewSyncTool", "New Bats fixed Tick Range " + tickName + " created", null);
                        }
                        else if (result == 2)
                        {
                            linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Changed Bats Tick Range type from dynamic to fixed for " + tickName, null);
                        }
                        else if (result == 3)
                        {
                            linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Changed Bats fixed Tick Range to " + range.Value + " for " + tickName, null);
                        }
                        else if (result == -1)
                        {
                            string message = "General failure processing " + tickName;
                            linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Bats fixed Tick Range - " + message, null);
                        }
                        else if (result == -2)
                        {
                            string message = "ExchangeMIC failure processing " + tickName + " with fixed value of " + range.Value;
                            linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Bats fixed Tick Range - " + message, null);
                        }
                        else
                        {
                            linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Bats fixed Tick Range - Unknown return value on ImportTickSize", null);
                        }
                    }
                }
                catch (Exception e)
                {
                    string message = "Bats fixed Tick Range Caused exception for " + tickName + " with fixed value of " + range.Value + "\n";
                    linq.ExceptionHandlerThrow("LiquidViewSyncTool", message + e.Message, null);

                }
            }


            //insert dynamic tick sizes
            foreach (string tickName in ranges.Where(a => a.Value.Count >= 2).Select(a => a.Key))
            {
                foreach (KeyValuePair<decimal, decimal> range in ranges[tickName].Where(a => a.Value != 0))
                {
                    try
                    {
                        int result = linq.ImportTickSize(tickName.Trim(), "BATE", range.Key, range.Value, ref tickSizeId);

                        if (result != 4)
                        {
                            if (result == 0)
                            {
                                Console.WriteLine("Created " + tickName);
                                linq.ExceptionHandlerThrow("LiquidViewSyncTool", "New Bats dynamic Tick Range " + tickName + " created", null);
                            }
                            else if (result == 1)
                            {
                                linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Added new Bats dynamic Tick Range to " + tickName + " " + range.Key + ":" + range.Value, null);
                            }
                            else if (result == 2)
                            {
                                linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Changed Bats Tick Range type from fixed to dynamic for " + tickName, null);
                            }
                            else if (result == -1)
                            {
                                string message = "General failure processing " + tickName;
                                linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Bats dynamic Tick Range - " + message, null);
                            }
                            else if (result == -2)
                            {
                                string message = "ExchangeMIC failure processing " + tickName + " with dynamic value of " + range.Value;
                                linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Bats dynamic Tick Range - " + message, null);
                            }
                            else
                            {
                                linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Bats dynamic Tick Range - Unknown return value on ImportTickSize", null);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        string message = "Bats dynamic Tick Range Caused exception for " + tickName + " with dynamic value of " + range.Value + "\n";
                        linq.ExceptionHandlerThrow("LiquidViewSyncTool", message + e.Message, null);
                    }
                }
            }


            return true;
        }


        public static bool ProcessSymbols(LiquidViewLinqDataContext linq, ref string symbols)
        {
            string[] rows = symbols.Split(SEPERATOR_ROW);
            string[] data;

            string currency;
            string bbg;
            int? stockId;
            string market;

            bool detected = false;
            int end = rows.Length - 1;

            for (int start = 2; start < end; start++)
            {
                data = rows[start].Trim().Split(SEPERATOR_COL);

                if (data.Length != SYMBOL_NUM_COL && !detected)
                {
                    string message = String.Format("Detected new Bats file format, contains {0} colums instead of {1}", data.Length, SYMBOL_NUM_COL);
                    linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Bats Symbols - " + message, null);
                    detected = true;
                }

                // update InstrumentStock               
                currency = data[SYMBOL_LOC_CCY];
                if (currency == "GBp" || currency == "GBX")
                    currency = "GBP";

                stockId = null;

                market = Program.CompareTheMeerkat(data[SYMBOL_PRI_MIC]);

                // inport instrument stock
                /*
                int result = linq.ImportInstrumentStock(
                    data[SYMBOL_PRI_MIC],
                    currency,
                    data[SYMBOL_PRI_ISIN],
                    null,
                    data[SYMBOL_PRI_UMTF],
                    data[SYMBOL_PRI_UMTF],
                    data[SYMBOL_PRI_NAME],
                    null,
                    null,
                    null,
                    null,
                    null,
                    false,
                    ref stockId);
                 * */

                bbg = data[SYMBOL_PRI_BBG]; 
                if(bbg != String.Empty)
                    bbg = bbg.Substring(0, bbg.LastIndexOf(' '));

                int result = linq.ImportInstrumentStockByUMTF(
                    data[SYMBOL_PRI_UMTF],
                    market,
                    currency,
                    data[SYMBOL_PRI_ISIN],
                    null,
                    data[SYMBOL_PRI_NAME],
                    null,
                    null,
                    bbg,
                    null,
                    null,
                    false,
                    ref stockId);

                if (result == 0)
                {
                    Console.WriteLine("Created " + data[SYMBOL_PRI_UMTF]);
                    linq.ExceptionHandlerThrow("LiquidViewSyncTool", "New Bats stock " + data[SYMBOL_PRI_UMTF] + " created", null);
                }
                else if (result == 1)
                {
                    //Console.WriteLine("Updated...");
                }
                else if (result == 2)
                {
                    Console.WriteLine("Changed MarketMIC for " + data[SYMBOL_PRI_UMTF]);
                    linq.ExceptionHandlerThrow("LiquidViewSyncTool", "WARNING: Market changed for " + data[SYMBOL_PRI_UMTF], null);
                }
                else if (result == 3)
                {
                    Console.WriteLine("Changed Currency for " + data[SYMBOL_PRI_UMTF]);
                    linq.ExceptionHandlerThrow("LiquidViewSyncTool", "WARNING: Currency changed for " + data[SYMBOL_PRI_UMTF], null);
                }
                else if (result == 4)
                {
                    Console.WriteLine("Created " + data[SYMBOL_PRI_UMTF]);
                    linq.ExceptionHandlerThrow("LiquidViewSyncTool", "WARNING: Market and Currency changed for " + data[SYMBOL_PRI_UMTF], null);
                }
                else if (result < 0)
                {
                    if (result == -1)
                    {
                        string message = "General failure processing " + data[SYMBOL_PRI_UMTF];
                        linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Bats Symbols - " + message, null);
                    }
                    else if (result == -2)
                    {
                        string message = "MarketMIC failure processing " + data[SYMBOL_PRI_UMTF] + " with " + market;
                        linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Bats Symbols - " + message, null);
                    }
                    else if (result == -3)
                    {
                        string message = "Currency failure processing " + data[SYMBOL_PRI_UMTF] + " with " + currency;
                        linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Bats Symbols - " + message, null);
                    }
                    else
                    {
                        string message = "Some other failure processing failure processing " + data[SYMBOL_PRI_UMTF];
                        linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Bats Symbols - " + message, null);
                    }
                }
                else
                {
                    linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Bats Symbols - Unknown return value on ImportInstrumentStock", null);
                }


                int? listingId = null;


                currency = data[SYMBOL_LOC_CCY];
                if (currency == "GBp")
                    currency = "GBX";

                bbg = data[SYMBOL_LOC_BBG];
                if (bbg != String.Empty)
                    bbg = bbg.Substring(0, bbg.LastIndexOf(' '));

                // inport instrument stock listing
                result = linq.ImportInstrumentStockListing(
                    stockId,
                    "BATE",
                    currency,
                    data[SYMBOL_LOC_TICK],
                    data[SYMBOL_PRI_UMTF],
                    bbg,
                    null,
                    ref listingId);

                if (result == 0)
                {
                    Console.WriteLine("Created Stock Listing for " + data[SYMBOL_PRI_UMTF]);
                    linq.ExceptionHandlerThrow("LiquidViewSyncTool", "New Bats Stock Listing " + data[SYMBOL_PRI_UMTF] + " created", null);
                }
                else if (result == 1)
                {
                    //Console.WriteLine("Updated...");
                }
                else if (result == -1)
                {
                    string message = "General failure processing " + data[SYMBOL_PRI_UMTF];
                    linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Bats Stock Listing - " + message, null);
                }
                else if (result == -2)
                {
                    string message = "ExchangMIC failure processing CHIX";
                    linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Bats Stock Listing - " + message, null);
                }
                else if (result == -3)
                {
                    string message = "StockId failure processing " + stockId;
                    linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Bats Stock Listing - " + message, null);
                }
                else if (result == -4)
                {
                    string message = "Tick range failure processing " + data[SYMBOL_PRI_UMTF] + " with " + data[SYMBOL_LOC_TICK];
                    linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Bats Stock Listing - " + message, null);
                }
                else
                {
                    linq.ExceptionHandlerThrow("LiquidViewSyncTool", "Bats Stock Listing - Unknown return value on ImportInstrumentStock", null);
                }
                

            }

            return true;
        }
    }
}
